package com.sandking.metadata;

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.sql.Connection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.sql.DataSource;

import com.sandking.metadata.decode.SK_JdbcType;
import com.sandking.metadata.decode.SK_SqlTypeDecode;
import com.sandking.metadata.template.DTP;

import freemarker.ext.beans.BeansWrapper;
import freemarker.template.Configuration;
import freemarker.template.DefaultObjectWrapper;
import freemarker.template.Template;

/**
 * @UserName : SandKing
 * @DataTime : 2013年11月27日 下午5:01:39
 * @Description ：生成器入口
 */
public class SK_Generate {
	private static Configuration cfg;
	private static SK_Database db;
	public static final Map<String, String> packageMap = new HashMap<String, String>();

	public static Configuration getConfiguration() {
		if (cfg == null) {
			cfg = new Configuration();
			cfg.setClassForTemplateLoading(DTP.class, "");
			cfg.setObjectWrapper(new DefaultObjectWrapper());
		}
		return cfg;
	}

	public static Configuration getConfiguration(String path) {
		if (cfg == null) {
			try {
				cfg = new Configuration();
				cfg.setDirectoryForTemplateLoading(new File(path));
				cfg.setObjectWrapper(new BeansWrapper());
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		return cfg;
	}

	public static void run(Connection conn, Object config, String path,
			Configuration cfg, boolean isConfig) {
		run(conn, config, path, cfg, new SK_JdbcType(), isConfig);
	}

	public static void run(DataSource ds, Object config, String path,
			Configuration cfg, boolean isConfig) {
		run(ds, config, path, cfg, new SK_JdbcType(), isConfig);
	}

	public static void run(Connection conn, Object config, String path,
			Configuration cfg, boolean isConfig, String... tableName) {
		run(conn, config, path, cfg, new SK_JdbcType(), isConfig, tableName);
	}

	public static void run(DataSource ds, Object config, String path,
			Configuration cfg, boolean isConfig, String... tableName) {
		run(ds, config, path, cfg, new SK_JdbcType(), isConfig, tableName);
	}

	public static void run(Connection conn, Object config, String path,
			Configuration cfg, SK_SqlTypeDecode sqlDecode, boolean isConfig) {
		examinePackage(path, isConfig);
		db = new SK_Database(conn, sqlDecode, config);
		loadDtaabase(isConfig, path);
	}

	public static void run(DataSource ds, Object config, String path,
			Configuration cfg, SK_SqlTypeDecode sqlDecode, boolean isConfig) {
		examinePackage(path, isConfig);
		db = new SK_Database(ds, sqlDecode, config);
		loadDtaabase(isConfig, path);
	}

	public static void run(Connection conn, Object config, String path,
			Configuration cfg, SK_SqlTypeDecode sqlDecode, boolean isConfig,
			String... tableName) {
		examinePackage(path, isConfig);
		db = new SK_Database(conn, sqlDecode, config);
		loadDtaabase(isConfig, path, tableName);
	}

	public static void run(DataSource ds, Object config, String path,
			Configuration cfg, SK_SqlTypeDecode sqlDecode, boolean isConfig,
			String... tableName) {
		examinePackage(path, isConfig);
		db = new SK_Database(ds, sqlDecode, config);
		loadDtaabase(isConfig, path, tableName);
	}

	/**
	 * 检查包是否存在，不存在则创建
	 * 
	 * @param path
	 */
	private static void examinePackage(String path, boolean isConfig) {
		File file = new File(path);
		if (!file.exists() || !file.isDirectory()) {
			file.mkdir();
		}
		if (!isConfig) {
			packageMap.put("bean", path + "/bean");
			packageMap.put("dao", path + "/dao");
			packageMap.put("cache", path + "/cache");
			packageMap.put("jedis", path + "/jedis");
			packageMap.put("imp", path + "/imp");
		} else {
			packageMap.put("cfg", path + "/cfg");
		}
		for (Map.Entry<String, String> packageVal : packageMap.entrySet()) {
			file = new File(packageVal.getValue());
			if (!file.exists() || !file.isDirectory()) {
				file.mkdir();
			}
		}
	}

	/**
	 * 生成全部表
	 * 
	 * @param tableName
	 */
	private static void loadDtaabase(boolean isConfig, String path) {
		if (db != null) {
			List<SK_Table> tables = db.getTables(isConfig);
			for (SK_Table sk_Table : tables) {
				String fileName = sk_Table.getD_tableName();
				if (!isConfig) {
					writerBean(fileName, cfg, sk_Table);
					writerCache(fileName, cfg, sk_Table);
					writerJedis(fileName, cfg, sk_Table);
					writerDao(fileName, cfg, sk_Table);
					writerImp(fileName, cfg, sk_Table);
				} else {
					writerCfg(fileName, cfg, sk_Table);
				}
			}
			if (isConfig) {
				writerCfgLoad(path, cfg, tables);
			} else {
				writerDbSave(path, cfg, tables);
			}
			completeInfo();
		}
	}

	/**
	 * 生成指定表
	 * 
	 * @param tableName
	 */
	private static void loadDtaabase(boolean isConfig, String path,
			String... tableName) {
		if (db != null) {
			List<SK_Table> tables = db.getTables(isConfig);
			for (SK_Table sk_Table : tables) {
				String fileName = sk_Table.getTableName();
				String d_fileName = sk_Table.getD_tableName();
				for (String table : tableName) {
					if (fileName.equals(table)) {
						if (!isConfig) {
							writerBean(d_fileName, cfg, sk_Table);
							writerCache(d_fileName, cfg, sk_Table);
							writerJedis(fileName, cfg, sk_Table);
							writerDao(d_fileName, cfg, sk_Table);
							writerImp(fileName, cfg, sk_Table);
						} else {
							writerCfg(fileName, cfg, sk_Table);
						}
						break;
					}
				}
			}
			if (isConfig) {
				writerCfgLoad(path, cfg, tables);
			} else {
				writerDbSave(path, cfg, tables);
			}
			completeInfo();
		}
	}

	private static void writerBean(String fileName, Configuration cfg,
			SK_Table table) {
		String filePath = packageMap.get("bean") + "/" + fileName + ".java";
		String packageName = packageMap.get("bean").replace("src/", "")
				.replace("/", ".");
		table.setPackageName(packageName);
		File file = new File(filePath);
		try {
			Template template = cfg.getTemplate("pojo.ftl");
			fileWriter(template, file, table);
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	private static void writerDao(String fileName, Configuration cfg,
			SK_Table table) {
		String filePath = packageMap.get("dao") + "/" + fileName + "Dao.java";
		String packageName = packageMap.get("dao").replace("src/", "")
				.replace("/", ".");
		table.setPackageName(packageName);
		File file = new File(filePath);
		try {
			Template template = cfg.getTemplate("dao.ftl");
			fileWriter(template, file, table);
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	private static void writerJedis(String fileName, Configuration cfg,
			SK_Table table) {
		String filePath = packageMap.get("jedis") + "/" + fileName
				+ "Jedis.java";
		String packageName = packageMap.get("jedis").replace("src/", "")
				.replace("/", ".");
		table.setPackageName(packageName);
		File file = new File(filePath);
		try {
			Template template = cfg.getTemplate("jedis.ftl");
			fileWriter(template, file, table);
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	private static void writerCache(String fileName, Configuration cfg,
			SK_Table table) {
		String filePath = packageMap.get("cache") + "/" + fileName
				+ "Cache.java";
		String packageName = packageMap.get("cache").replace("src/", "")
				.replace("/", ".");
		table.setPackageName(packageName);
		File file = new File(filePath);
		try {
			Template template = cfg.getTemplate("cache.ftl");
			fileWriter(template, file, table);
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	private static void writerImp(String fileName, Configuration cfg,
			SK_Table table) {
		String filePath = packageMap.get("imp") + "/" + fileName + "Imp.java";
		String packageName = packageMap.get("imp").replace("src/", "")
				.replace("/", ".");
		table.setPackageName(packageName);
		File file = new File(filePath);
		// 扩展类已存在就不在重写
		if (file.exists()) {
			return;
		}
		try {
			Template template = cfg.getTemplate("imp.ftl");
			fileWriter(template, file, table);
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	private static void writerCfg(String fileName, Configuration cfg,
			SK_Table table) {
		String filePath = packageMap.get("cfg") + "/" + fileName + "Cfg.java";
		String packageName = packageMap.get("cfg").replace("src/", "")
				.replace("/", ".");
		table.setPackageName(packageName);
		File file = new File(filePath);
		try {
			Template template = cfg.getTemplate("cfg.ftl");
			fileWriter(template, file, table);
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	private static void writerCfgLoad(String path, Configuration cfg,
			List<SK_Table> tables) {
		String filePath = path + "/ConfigLoad.java";
		String packageName = path.replace("src/", "").replace("/", ".");
		SK_Cfg skCfg = new SK_Cfg("ConfigLoad", packageName, tables);
		File file = new File(filePath);
		try {
			Template template = cfg.getTemplate("cfgLoad.ftl");
			fileWriter(template, file, skCfg);
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	private static void writerDbSave(String path, Configuration cfg,
			List<SK_Table> tables) {
		String filePath = path + "/DbSave.java";
		String packageName = path.replace("src/", "").replace("/", ".");
		SK_Cfg skCfg = new SK_Cfg("DbSave", packageName, tables);
		File file = new File(filePath);
		try {
			Template template = cfg.getTemplate("dbSave.ftl");
			fileWriter(template, file, skCfg);
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	private static void fileWriter(Template template, File file, Object table) {
		try {
			FileWriter fileWriter = new FileWriter(file);
			template.process(table, fileWriter);
			fileWriter.flush();
			// 打印输出
			Writer writer = new OutputStreamWriter(System.out);
			template.process(table, writer);
			writer.flush();
			System.out.println();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	public static void completeInfo() {
		System.out.println("*********************************************");
		System.out.println("*                                           *");
		System.out.println("**********代码生成完成-请刷新项目！**********");
		System.out.println("*                                           *");
		System.out.println("*********************************************");
	}
}
